package com.liber.sun.controller;

import com.liber.sun.domain.AdvanceRecord;
import com.liber.sun.domain.Record;
import com.liber.sun.service.AdvanceRecordService;
import com.liber.sun.service.RecordService;
import com.liber.sun.support.*;
import com.liber.sun.thread.AdvanceCallable;
import com.liber.sun.thread.AdvanceHandle;
import com.liber.sun.utils.ResultUtil;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.*;


/**
 * Created by sunlingzhi on 2018/2/1.
 */
@RestController //默认返回json格式
@RequestMapping("/refactor")
public class RefactorController {


    @Value("${web.upload-path}services/refactor/")
    private String ROOT;

    @Autowired
    private InstanceBean instanceBean;
    @Autowired
    private RecordService recordService;
    @Autowired
    private AdvanceRecordService advanceRecordService;

    @ApiOperation(value = "调用重构服务", notes = "")
    @RequestMapping(value = "/call", method = RequestMethod.GET)
    public Result<String> refactorRun(@RequestParam("id") String id,
                                      @RequestParam("method") String method,
                                      @RequestParam("inputs") String[] inputs,
                                      @RequestParam("outputs") String[] outputs,
                                      @RequestParam("username") String username
    ) throws IOException, SAXException, ParserConfigurationException {
        RefactorNode refactorData = new RefactorNode(id, method, inputs, outputs);
        UUID uuid = UUID.randomUUID();
        Instance instance = new Instance<>(uuid.toString(), id, method, new Date(), 0, username, refactorData);
        instanceBean.addInstance(instance);
        ProcessResponse processResponse = refactorData.compute(ROOT, username);
        instanceBean.removeByGuid(uuid.toString());
        Record record = new Record(null, "refactor", id,new Date(), processResponse.getOperator(), processResponse.getInfo(), processResponse.getFlag());
        return ResultUtil.success(recordService.addRecord(record));
    }

    @ApiOperation(value = "获取重构服务指定的方法", notes = "返回methods")
    @RequestMapping(value = "/methods", method = RequestMethod.GET)
    public Result<String> getMethods(@RequestParam("id") String id
    ) {
        return ResultUtil.success("返回methods");
    }


    @ApiOperation(value = "获取重构服务数据的schema", notes = "schema参数为schema的路径，返回schema的内容")
    @RequestMapping(value = "/paramSchema", method = RequestMethod.GET)
    public Result<String> getSchema(@RequestParam("id") String id,
                                    @RequestParam("schema") String schema
    ) {

        return ResultUtil.success("返回methods");
    }


    @ApiOperation(value = "重构服务的串联使用", notes = "传递对应JSON串到后台")
    @RequestMapping(value = "/advance/{username}", method = RequestMethod.POST)
    public Result advanceRefactor(@RequestBody List<RefactorNode> nodeList,
                                  @PathVariable("username") String username) throws InterruptedException {
        UUID uuid = UUID.randomUUID();
        Instance instance = new Instance<>(uuid.toString(), "重构服务串联", "重构服务串联", new Date(), 0, username, nodeList);
        instanceBean.addInstance(instance);
        AdvanceHandle advanceHandle = new AdvanceHandle(nodeList, username, ROOT);
        ExecutorService pool = Executors.newCachedThreadPool();
        List<Future<RefactorNode>> futureList = new ArrayList<>();

        //注意这里要深度拷贝
        List<RefactorNode> list = new ArrayList<>(nodeList);
        //拥有多少个节点就开启多少个进程的Runnable,就有多少个future
        for (int i = 0; i < nodeList.size(); i++) {
            AdvanceCallable advanceCallable = new AdvanceCallable(advanceHandle, i);
            Future<RefactorNode> future = pool.submit(advanceCallable);
            futureList.add(future);
        }

        //针对每个线程令其阻塞
        for (int i = 0; i < futureList.size(); i++) {
            RefactorNode refactorNode = null;
            try {
                refactorNode = futureList.get(i).get(1, TimeUnit.DAYS);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                nodeList.get(i).setIsFinished(2);
                refactorNode=nodeList.get(i);
            } finally {
                list.set(i, refactorNode);
            }
        }

        pool.shutdown();
        instanceBean.removeByGuid(uuid.toString());
        return ResultUtil.success(advanceRecordService.addAdvanceRecord(new AdvanceRecord(null,new Date(), list)));
    }
}
